package com.sfx.admin.common.biz.user;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.sfx.admin.common.constants.RedisCacheConstants;
import com.sfx.admin.common.convention.exception.ClientException;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.sfx.admin.common.enums.UserErrorCodeEnums.USER_LOGIN_VERIFY_ERROR;

/**
 * 用户信息传输过滤器
 */
@RequiredArgsConstructor
@Component
public class UserTransmitFilter implements Filter {

    private static final List<String> WHITE_URL = Arrays.asList(
            // 登陆
            "/api/short-link/admin/v1/user/login",
            // 查询是否有用户
            "/api/short-link/admin/v1/user/has-username",
            // 检查用户是否登陆
            "/api/short-link/admin/v1/user/check-login"
    );

    private final StringRedisTemplate stringRedisTemplate;

    @SneakyThrows
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // 1. 白名单跳过
        String requestURI = request.getRequestURI();
        if (!WHITE_URL.contains(requestURI)) {
            // 需要进行校验
            // /api/short-link/admin/v1/user
            if (!(Objects.equals(requestURI, "/api/short-link/admin/v1/user") && request.getMethod().equals("POST"))) {
                // 1. 拿到username
                String username = request.getHeader("username");
                // 2. 拿到token
                String token = request.getHeader("token");
                if (StrUtil.isAllBlank(username, token)) {
                    returnJson((HttpServletResponse) servletResponse, "username or token is null");
                    throw new ClientException(USER_LOGIN_VERIFY_ERROR);
                }
                Object jsonString = stringRedisTemplate.opsForHash().get(RedisCacheConstants.SHORT_LINK_USER_LOGIN_CACHE_KEY + username, token);
                UserInfo userInfo = JSON.parseObject(String.valueOf(jsonString), UserInfo.class);
                if (userInfo == null) {
                    returnJson((HttpServletResponse) servletResponse, "username or token is error");
                    throw new ClientException(USER_LOGIN_VERIFY_ERROR);
                }
                UserContext.setUserInfo(userInfo);
            }
        }
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            UserContext.removeUser();
        }
    }

    private void returnJson(HttpServletResponse response, String json) throws Exception {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try (PrintWriter writer = response.getWriter()) {
            writer.print(json);
        }
    }
}